/**
 * 给定数组A和V，一共要操作D次，每次有两种可能的操作：
 * 1. 第i次操作选择Vi，将[1...Vi]中的A元素均加一，如果V没有Vi，则循环使用
 * 2. 对所有A元素，如果Ai==i则加一分，计算完总得分之后，将A清零
 * 问D次操作后最多的多少分
 * 由于操作2会清零，清零后再累加会发现不可能再同时获得2分及其以上
 * 因此一旦执行清零操作后，以后的最佳策略就是1、2轮流操作，且每轮拿1分
 * 于是关键就在于第一次清零操作发生在什么时候
 * 枚举第一次清零操作发生的时间，求最大值即可
 * D很大，显然不能挨个枚举
 * 原来考虑只需枚举到N即可，因为经过N次加法，Ai就必然到达了得分的位置。但这个想法是错误的。
 * 一个最简单的例子就是令前面的数一开始就超范围，后面的数为等差数列。
 * 再将V设计为前小后大，则有可能在N次操作后的某次操作一口气获得若干分且超过之前的分数
 * 枚举到2N即可。因为到2N操作再执行清零操作，最多也只能获得N分
 * 而从一开始就进入循环，也能获得N分，效果一样
 * 且2N以后，分数不可能高于一开始就循环，因此只有前2N需要枚举
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;

using llt = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;

int N, K, D;
vi A;
vi V;

llt proc(){
    llt ans = 0;
    for(int i=1;i<=N;++i)if(A[i]==i)++ans;
    ans += D - 1 >> 1;

    for(int idx,i=1;i<=N+N;++i){
        if(D - i - 1 < 0) break;
        idx = i;
        if(idx > K) idx = (idx - 1) % K + 1;
        llt tmp = 0;
        for(int j=1;j<=V[idx];++j){
            if((A[j] += 1) == j){
                ++tmp;
            }
        }
        for(int j=V[idx]+1;j<=N;++j)if(A[j] == j)++tmp;
        tmp += D - i - 1 >> 1;
        ans = max(ans, tmp);
    }
    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
    int nofkase = 1;
    cin >> nofkase;
    while(nofkase--){
        cin >> N >> K >> D;
        A.assign(N + 1, 0);
        for(int i=1;i<=N;++i) cin >> A[i];
        V.assign(K + 1, 0);
        for(int i=1;i<=K;++i) cin >> V[i];
        cout << proc() << "\n";
    }
    return 0;
}